package com.longcai.cm.pay.ali;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeCancelModel;
import com.alipay.api.domain.AlipayTradeCreateModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeCancelRequest;
import com.alipay.api.request.AlipayTradeCreateRequest;
import com.alipay.api.request.AlipayTradeRefundApplyRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeCreateResponse;
import com.alipay.api.response.AlipayTradeRefundApplyResponse;
import com.longcai.cm.common.constant.DomainConfig;
import com.longcai.cm.pay.wx.domain.WxRefundParam;
import com.longcai.cm.utils.DateUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URLEncoder;
import java.util.Calendar;

/**
 * @author libingxing
 */
public class AliPayApi {

    private static final Logger LOGGER = LoggerFactory.getLogger(AliPayApi.class);

    public static String createOrderAliPay(String specifyName, String orderNum, String payAmount, String passBack, String notifyUrl) throws Exception {
//        设置请求网关 (gateway)、应用 id (app_id)、应用私钥 (private_key)、编码格式 (charset)、支付宝公钥 (alipay_public_key)、签名类型 (sign_type)即可，报文请求时会自动进行签名。
        AlipayClient alipayClient = getAlipayClient();
        AlipayTradeAppPayRequest requestParam = new AlipayTradeAppPayRequest();
//        构建订单模型
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
//        订单价格
        model.setTotalAmount(payAmount);
//        商品类型名称
        model.setSubject(specifyName);
//        订单号
        model.setOutTradeNo(orderNum);
//        0虚拟 1实物
        model.setGoodsType("1");
//        自定义参数  URLEncoder用于防止传输乱码
        model.setPassbackParams(URLEncoder.encode(passBack, "utf-8"));
//        订单有效期
        model.setTimeExpire(DateUtil.format(DateUtil.offsetMinute(Calendar.getInstance().getTime(), 30), DateUtils.DEFAULT_DATETIME_FORMAT));
//        页面跳转异步通知页面路径
        requestParam.setNotifyUrl(DomainConfig.LOCALHOST + notifyUrl);
//        配置model
        requestParam.setBizModel(model);

        LOGGER.info("支付宝开始支付：" + JSON.toJSONString(requestParam));
        AlipayTradeAppPayResponse response = alipayClient.sdkExecute(requestParam);
        LOGGER.info("支付宝开始支付：" + response.isSuccess());
        LOGGER.info("支付宝开始支付：" + response.getBody());
        LOGGER.info("支付宝开始支付：" + response.getMsg());
        return response.isSuccess() ? response.getBody() : response.getMsg();
    }

    public static String createOrderAliNative(String specifyName, String orderNum, String payAmount, String passBack, String notifyUrl) throws Exception {
//        设置请求网关 (gateway)、应用 id (app_id)、应用私钥 (private_key)、编码格式 (charset)、支付宝公钥 (alipay_public_key)、签名类型 (sign_type)即可，报文请求时会自动进行签名。
        AlipayClient alipayClient = getAlipayClient();
        AlipayTradeCreateRequest requestParam = new AlipayTradeCreateRequest();
//        构建订单模型
        AlipayTradeCreateModel model = new AlipayTradeCreateModel();
//        订单价格
        model.setTotalAmount(payAmount);
//        商品类型名称
        model.setSubject(specifyName);
//        订单号
        model.setOutTradeNo(orderNum);
//        页面跳转异步通知页面路径
        requestParam.setNotifyUrl(DomainConfig.LOCALHOST + notifyUrl);
//        配置model
        requestParam.setBizModel(model);
        AlipayTradeCreateResponse response = alipayClient.sdkExecute(requestParam);
        LOGGER.info("支付宝开始支付：" + response.isSuccess());
        LOGGER.info("支付宝开始支付：" + response.getBody());
        LOGGER.info("支付宝开始支付：" + response.getMsg());
        return response.isSuccess() ? response.getBody() : response.getMsg();
    }

    public static void closeOrder(String orderNum) throws AlipayApiException {
//        设置请求网关 (gateway)、应用 id (app_id)、应用私钥 (private_key)、编码格式 (charset)、支付宝公钥 (alipay_public_key)、签名类型 (sign_type)即可，报文请求时会自动进行签名。
        AlipayClient alipayClient = getAlipayClient();
        AlipayTradeCancelRequest requestParam = new AlipayTradeCancelRequest();
        AlipayTradeCancelModel model = new AlipayTradeCancelModel();
        model.setOutTradeNo(orderNum);
        requestParam.setBizModel(model);
        alipayClient.sdkExecute(requestParam);
    }

    public static String refundOrderAliPay(WxRefundParam param) throws Exception {
//        设置请求网关 (gateway)、应用 id (app_id)、应用私钥 (private_key)、编码格式 (charset)、支付宝公钥 (alipay_public_key)、签名类型 (sign_type)即可，报文请求时会自动进行签名。
        AlipayClient alipayClient = getAlipayClient();
        AlipayTradeRefundApplyRequest requestParam = new AlipayTradeRefundApplyRequest();
//        配置model
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setOutTradeNo(param.getOrderNum());
        model.setRefundAmount(param.getTotal() + "");
        model.setOutRequestNo(param.getRefundId());
        requestParam.setBizModel(model);
        AlipayTradeRefundApplyResponse response = alipayClient.execute(requestParam);
        LOGGER.info("支付宝退款状态：" + response.isSuccess());
        LOGGER.info("支付宝退款回执：" + JSON.toJSONString(response.getBody()));
        return response.isSuccess() ? "" : response.getMsg();
    }

    @NotNull
    private static AlipayClient getAlipayClient() throws AlipayApiException {
        return new DefaultAlipayClient(getAlipayConfig());
    }

    private static AlipayConfig getAlipayConfig() {
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setServerUrl(AliPayConfig.URL);
        alipayConfig.setAppId(AliPayConfig.APP_ID);
        alipayConfig.setPrivateKey(AliPayConfig.RSA_PRIVATE_KEY);
        alipayConfig.setFormat(AliPayConfig.FORMAT);
        alipayConfig.setAlipayPublicKey(AliPayConfig.ALIPAY_PUBLIC_KEY);
        alipayConfig.setCharset(AliPayConfig.CHARSET);
        alipayConfig.setSignType(AliPayConfig.SIGNTYPE);
        return alipayConfig;
    }
}
